home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.000
/
crossfir
/
crossfire-0.92.4.client
/
xutil.c
< prev
Wrap
C/C++ Source or Header
|
1996-04-21
|
24KB
|
881 lines
#include <X11/keysym.h>
#include "def-keys.h"
/* This contains varous 'support' functions. These functions will probably
* go mostly unaltered between different toolkits, as long as X11 is still
* used. This file is not compiled seperately, rather it is included by
* x11.c, so all statics will still work fine.
*/
static char *colorname[] = {
"Black", /* 0 */
"White", /* 1 */
"Navy", /* 2 */
"Red", /* 3 */
"Orange", /* 4 */
"DodgerBlue", /* 5 */
"DarkOrange2", /* 6 */
"SeaGreen", /* 7 */
"DarkSeaGreen", /* 8 */ /* Used for window background color */
"Grey50", /* 9 */
"Sienna", /* 10 */
"Gold", /* 11 */
"Khaki" /* 12 */
};
static int allocate_colors(Display *disp, Window w, long screen_num,
Colormap *colormap, XColor discolor[16])
{
int i, tried = 0, depth=0, iscolor;
Status status;
Visual *vis;
XColor exactcolor;
iscolor = 1;
vis = DefaultVisual(disp,screen_num);
if (vis->class >= StaticColor) {
*colormap = DefaultColormap(disp,screen_num);
depth = DefaultDepth(disp,screen_num);
}
else {
printf("Switching to black and white.\n");
printf("You have a black and white terminal.\n");
return 0;
}
try_private:
if (depth > 3 && iscolor) {
unsigned long pixels[13];
for (i=0; i<13; i++){
status = XLookupColor(disp,*colormap, colorname[i],&exactcolor,
&discolor[i]);
if (!status){
printf("Can't find colour %s.\n", colorname[i]);
printf("Switching to black and white.\n");
iscolor = 0;
break;
}
status = XAllocColor(disp,*colormap,&discolor[i]);
if (!status) {
if (!tried) {
printf( "Not enough colours. Trying a private colourmap.\n");
XFreeColors(disp, *colormap, pixels, i-1, 0);
*colormap = XCreateColormap(disp, w, vis, AllocNone);
XSetWindowColormap(disp, w, *colormap);
tried = 1;
goto try_private;
} else {
printf( "Failed. Switching to black and white.\n");
iscolor = 0;
break;
}
}
pixels[i] = discolor[i].pixel;
}
}
return iscolor;
}
/*
* This function adds the path to the fontpath of the given display.
* It's mostly copied from the X11R5 distribution.
*/
static void set_font_path(Display *dpy, char *path) {
char **currentList = NULL; int ncurrent = 0;
char **directoryList = NULL; int ndirs = 0;
currentList = XGetFontPath (dpy, &ncurrent);
if(currentList==NULL) {
fprintf(stderr,"Unable to get old font path.\n");
return;
}
{
register char *cp = path;
ndirs=1;
while((cp=strchr(cp, ','))!=NULL)
ndirs++,cp++;
directoryList=(char **) malloc(ndirs*sizeof(char *));
if(!directoryList) {
fprintf(stderr,"Unable to allocate memory for font path directory.\n");
return;
}
}
{
int i=0;
char *cp = path;
directoryList[i++]=cp;
while((cp=strchr(cp, ','))!=NULL)
directoryList[i++]=cp+1,
*cp++='\0';
if(i!=ndirs) {
fprintf(stderr,"Internal error, only parsed %d of %d dirs.\n",i,ndirs);
return;
}
}
{
int nnew=ndirs+ncurrent;
char **newList = (char **) malloc (nnew * sizeof(char *));
if(!newList) {
fprintf(stderr,"Couldn't get memory for new fontpath.\n");
return;
}
/* #if defined(SYSV) || defined(SVR4) */
memcpy((void *)newList,(void *)directoryList,
(unsigned) (ndirs*sizeof (char *)));
memcpy((void *) (newList + ndirs), (void *) currentList,
(unsigned) (ncurrent*sizeof (char *)));
XSetFontPath(dpy,newList, nnew);
free((char *)newList);
}
if (directoryList)
free((char *) directoryList);
if (currentList)
XFreeFontPath (currentList);
}
/*
* Checks if "crossfire" is present somewhere in the fontpath of
* the given display.
*/
static int check_font_path(Display *dpy) {
int count;
char **list;
list = XListFonts(dpy, font_graphic, 1, &count);
fprintf(stderr, "Matching fonts to %s: %d (%s)\n",
font_graphic,count,count?*list:"");
XFreeFontNames(list);
return count;
}
/*
* Uses check_font_path() and set_font_path() to check and, if needed
* fix the fontpath for the player.
* Function changed around to make it useful for the client.
* Passing the player struct to this is not required - xio.c
* can use the return value to set the use_pixmaps value in the
* player struct. name is only passed to give better error
* messages.
*/
static int fixfontpath(Display *disp, char *name) {
if (check_font_path(disp))
return 0;
fprintf(stderr,"Trying to fix fontpath for display %s.\n",name);
set_font_path(disp,FONTDIR);
if(check_font_path(disp))
return 0;
fprintf(stderr,"Failed, switching to pixmaps (this might take a while).\n");
return 1;
}
/***********************************************************************
*
* Key board input translations are handled here. We don't deal with
* the events, but rather KeyCodes and KeySyms.
*
* It would be nice to deal with only KeySyms, but many keyboards
* have keys that do not correspond to a KeySym, so we do need to
* support KeyCodes.
*
***********************************************************************/
static KeyCode firekey[2], runkey[2], commandkey, *bind_keycode;
static KeySym firekeysym[2], runkeysym[2], commandkeysym,*bind_keysym;
static int bind_flags=0;
static char bind_buf[MAX_BUF];
#define KEYF_NORMAL 0x01 /* Used in normal mode */
#define KEYF_FIRE 0x02 /* Used in fire mode */
#define KEYF_RUN 0x04 /* Used in run mode */
#define KEYF_MODIFIERS 0x07 /* Mask for actual keyboard modifiers, */
/* not action modifiers */
#define KEYF_EDIT 0x08 /* Line editor */
extern char *directions[9];
typedef struct Keys {
uint8 flags;
sint8 direction;
KeySym keysym;
char *command;
struct Keys *next;
} Key_Entry;
#if 0
static void clear_key_entry(Key_Entry *key)
{
if (key==NULL) return;
if (key->command) {
free(key->command);
key->command=NULL;
}
key->flags=0;
key->direction=-1;
key->next=NULL;
key->keysym=NoSymbol;
}
#endif
/* Key codes can only be from 8-255 (at least according to
* the X11 manual. This is easier than using a hash
* table, quicker, and doesn't use much more space.
*/
#define MAX_KEYCODE 255
static Key_Entry *keys[256];
/* Updates the keys array with the keybinding that is passed. All the
* arguments are pretty self explanatory. flags is the various state
* that the keyboard is in.
*/
static void insert_key(KeySym keysym, KeyCode keycode, int flags, char *command)
{
Key_Entry *newkey;
int i, direction=-1;
if (keycode>MAX_KEYCODE) {
fprintf(stderr,"Warning insert_key:keycode that is passed is greater than 255.\n");
keycode=0; /* hopefully the rest of the data is OK */
}
if (keys[keycode]==NULL) {
keys[keycode]=malloc(sizeof(Key_Entry));
keys[keycode]->command=NULL;
keys[keycode]->next=NULL;
}
newkey=keys[keycode];
/* Try to find out if the command is a direction command. If so, we
* then want to keep track of this fact, so in fire or run mode,
* things work correctly.
*/
for (i=0; i<9; i++)
if (!strcmp(command, directions[i])) {
direction=i;
break;
}
if (keys[keycode]->command!=NULL) {
/* if keys[keycode]->command is not null, then newkey is
* the same as keys[keycode]->command.
*/
while (newkey->next!=NULL)
newkey = newkey->next;
newkey->next = malloc(sizeof(Key_Entry));
newkey = newkey->next;
/* This is the only initializing we need to do - the other fields
* will get filled in by the passed parameters
*/
newkey->next = NULL;
}
newkey->keysym = keysym;
newkey->flags = flags;
newkey->command = strdup_local(command);
newkey->direction = direction;
}
static void parse_keybind_line(char *buf, int line)
{
char *cp, *cpnext;
KeySym keysym;
KeyCode keycode;
int flags;
if (buf[0]=='#' || buf[0]=='\n') return;
if ((cpnext = strchr(buf,' '))==NULL) {
fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line,buf);
return;
}
*cpnext++ = '\0';
keysym = XStringToKeysym(buf);
cp = cpnext;
if ((cpnext = strchr(cp,' '))==NULL) {
fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line, cp);
return;
}
*cpnext++ = '\0';
/* If we can, convert the keysym into a keycode. */
keycode = atoi(cp);
if (keysym!=NoSymbol) {
keycode = XKeysymToKeycode(display, keysym);
/* It is possible that we get a keysym that we can not convert
* into a keycode (such a case might be binding the key on
* one system, and later trying to run on another system that
* doesn't have that key.
* While the client will not be able to use it this invocation,
* it may be able to use it in the future. As such, don't throw
* it away, but at least print a warning message.
*/
if (keycode==0) {
fprintf(stderr,"Warning: could not convert keysym %s into keycode, ignoring\n",
buf);
}
}
cp = cpnext;
if ((cpnext = strchr(cp,' '))==NULL) {
fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line, cp);
return;
}
*cpnext++ = '\0';
flags = 0;
while (*cp!='\0') {
switch (*cp) {
case 'A':
flags |= KEYF_NORMAL | KEYF_FIRE | KEYF_RUN;
break;
case 'N':
flags |= KEYF_NORMAL;
break;
case 'F':
flags |= KEYF_FIRE;
break;
case 'R':
flags |= KEYF_RUN;
break;
case 'E':
flags |= KEYF_EDIT;
break;
default:
fprintf(stderr,"Warning: Unknown flag (%c) line %d in key binding file\n",
*cp, line);
}
cp++;
}
/* Rest of the line is the actual command. Lets kill the newline */
cpnext[strlen(cpnext)-1]='\0';
insert_key(keysym, keycode, flags, cpnext);
}
static void init_default_keybindings()
{
char buf[MAX_BUF];
int i;
for(i=0;i< sizeof(def_keys)/sizeof(char *);i++) {
strcpy(buf,def_keys[i]);
parse_keybind_line(buf,i);
}
}
/* This reads in the keybindings, and initializes any special values.
* called by init_windows.
*/
static void init_keys()
{
int i, line=0;
FILE *fp;
char buf[MAX_BUF];
commandkeysym = XK_apostrophe;
commandkey =XKeysymToKeycode(display,XK_apostrophe);
if (!commandkey) {
commandkeysym =XK_acute;
commandkey =XKeysymToKeycode(display, XK_acute);
}
firekeysym[0] =XK_Shift_L;
firekey[0] =XKeysymToKeycode(display, XK_Shift_L);
firekeysym[1] =XK_Shift_R;
firekey[1] =XKeysymToKeycode(display, XK_Shift_R);
runkeysym[0] =XK_Control_L;
runkey[0] =XKeysymToKeycode(display, XK_Control_L);
runkeysym[1] =XK_Control_R;
runkey[1] =XKeysymToKeycode(display, XK_Control_R);
for (i=0; i<=MAX_KEYCODE; i++) {
keys[i] = NULL;
}
/* We now try to load the keybindings. First place to look is the
* users home directory, "~/.crossfire/keys". Using a directory
* seems like a good idea, in the future, additional stuff may be
* stored.
*
* The format is described in the def_keys file. Note that this file
* is the same as what it was in the server distribution. To convert
* bindings in character files to this format, all that needs to be done
* is remove the 'key ' at the start of each line.
*
* We need at least one of these keybinding files to exist - this is
* where the various commands are defined. In theory, we actually
* don't need to have any of these defined -- the player could just
* bind everything. Probably not a good idea, however.
*/
sprintf(buf,"%s/.crossfire/keys", getenv("HOME"));
if ((fp=fopen(buf,"r"))==NULL) {
fprintf(stderr,"Could not open ~/.crossfire/keys, trying to load global bindings\n");
if (client_libdir==NULL) {
init_default_keybindings();
return;
}
sprintf(buf,"%s/def_keys", client_libdir);
if ((fp=fopen(buf,"r"))==NULL) {
init_default_keybindings();
return;
}
}
while (fgets(buf, MAX_BUF, fp)) {
line++;
parse_keybind_line(buf,line);
}
fclose(fp);
}
/* The only things we actually care about is the run and fire keys.
* Other key releases are not important.
* If it is the release of a run or fire key, we tell the client
* to stop firing or running. In some cases, it is possible that we
* actually are not running or firing, and in such cases, the server
* will just ignore the command.
*/
static void parse_key_release(KeyCode kc, KeySym ks) {
/* Only send stop firing/running commands if we are in actual
* play mode. Something smart does need to be done when the character
* enters a non play mode with fire or run mode already set, however.
*/
if (cpl.input_state != Playing) return;
if (kc==firekey[0] || ks==firekeysym[0] ||
kc==firekey[1] || ks==firekeysym[1]) {
#if 0 /* Nice idea, but unfortunately prints too many false results */
if (cpl.echo_bindings) draw_info("stop fire",NDI_BLACK);
#endif
cpl.fire_on=0;
stop_fire();
}
else if (kc==runkey[0] || ks==runkeysym[0] ||
kc==runkey[1] || ks==runkeysym[1]) {
cpl.run_on=0;
if (cpl.echo_bindings) draw_info("stop run",NDI_BLACK);
stop_run();
}
}
/* This parses a keypress. It should only be called win in Playing
* mode.
*/
static void parse_key(char key, KeyCode keycode, KeySym keysym)
{
Key_Entry *keyentry, *first_match=NULL;
int present_flags=0;
char buf[MAX_BUF];
if (keycode == commandkey && keysym==commandkeysym) {
draw_prompt(">");
cpl.input_state = Command_Mode;
cpl.no_echo=FALSE;
return;
}
if (keycode == firekey[0] || keysym==firekeysym[0] ||
keycode == firekey[1] || keysym==firekeysym[1]) {
cpl.fire_on=1;
return;
}
if (keycode == runkey[0] || keysym==runkeysym[0] ||
keycode==runkey[1] || keysym==runkeysym[1]) {
cpl.run_on=1;
return;
}
if (cpl.run_on) present_flags |= KEYF_RUN;
if (cpl.fire_on) present_flags |= KEYF_FIRE;
if (present_flags ==0) present_flags = KEYF_NORMAL;
keyentry = keys[keycode];
while (keyentry!=NULL) {
if ((keyentry->keysym!=NoSymbol && keyentry->keysym!=keysym) ||
(!(keyentry->flags & present_flags))) {
keyentry=keyentry->next;
continue;
}
first_match = keyentry;
/* Try to find a prefect match */
if ((keyentry->flags & KEYF_MODIFIERS)!= present_flags) {
keyentry=keyentry->next;
continue;
}
else break;
}
if (first_match!=NULL) {
char buf[MAX_BUF];
if (first_match->flags & KEYF_EDIT) {
strcpy(cpl.input_text, first_match->command);
cpl.input_state = Command_Mode;
draw_prompt(">");
draw_prompt(cpl.input_text);
return;
}
if (first_match->direction>=0) {
if (cpl.fire_on) {
sprintf(buf,"fire %s", first_match->command);
fire_dir(first_match->direction);
}
else if (cpl.run_on) {
run_dir(first_match->direction);
sprintf(buf,"run %s", first_match->command);
}
else {
strcpy(buf,first_match->command);
send_command(first_match->command);
}
if (cpl.echo_bindings) draw_info(buf,NDI_BLACK);
}
else {
if (cpl.echo_bindings) draw_info(first_match->command,NDI_BLACK);
send_command(first_match->command);
}
return;
}
if (key>='0' && key<='9') {
cpl.count = cpl.count*10 + (key-'0');
if (cpl.count>100000) cpl.count%=100000;
return;
}
sprintf(buf, "Key unused (%s%s%s)",
(cpl.fire_on? "Fire&": ""),
(cpl.run_on ? "Run&" : ""),
XKeysymToString(keysym));
draw_info(buf,NDI_BLACK);
cpl.count=0;
}
/* This returns a character string desribing the key. */
/* If save_mode is true, it means that the format used for saving
* the information is used, instead of the usual format for displaying
* the information in a friendly manner.
*/
static char * get_key_info(Key_Entry *key, KeyCode kc, int save_mode)
{
static char buf[MAX_BUF];
char buff[MAX_BUF];
int bi=0;
if ((key->flags & KEYF_MODIFIERS) == KEYF_MODIFIERS)
buff[bi++] ='A';
else {
if (key->flags & KEYF_NORMAL)
buff[bi++] ='N';
if (key->flags & KEYF_FIRE)
buff[bi++] ='F';
if (key->flags & KEYF_RUN)
buff[bi++] ='R';
}
if (key->flags & KEYF_EDIT)
buff[bi++] ='E';
buff[bi]='\0';
if (save_mode) {
if(key->keysym == NoSymbol) {
sprintf(buf, "(null) %i %s %s",
kc,buff, key->command);
}
else {
sprintf(buf, "%s %i %s %s",
XKeysymToString(key->keysym), kc,
buff, key->command);
}
}
else {
if(key->keysym == NoSymbol) {
sprintf(buf, "key (null) (%i) %s %s",
kc,buff, key->command);
}
else {
sprintf(buf, "key %s (%i) %s %s",
XKeysymToString(key->keysym), kc,
buff, key->command);
}
}
return buf;
}
/* Shows all the keybindings. The original function from c_bind.c had
* two modes - one mode which would only show non default bindings, the
* other where it should show all bindings. No supported - there is
* no 'default' bindings - all bindings exist.
*/
static void show_keys()
{
int i, count=1;
Key_Entry *key;
char buf[MAX_BUF];
sprintf(buf, "Commandkey %s (%d)", XKeysymToString(commandkeysym),
commandkey);
draw_info(buf,NDI_BLACK);
sprintf(buf, "Firekeys 1: %s (%d), 2: %s (%d)",
XKeysymToString(firekeysym[0]), firekey[0],
XKeysymToString(firekeysym[1]), firekey[1]);
draw_info(buf,NDI_BLACK);
sprintf(buf, "Runkeys 1: %s (%d), 2: %s (%d)",
XKeysymToString(runkeysym[0]), runkey[0],
XKeysymToString(runkeysym[1]), runkey[1]);
draw_info(buf,NDI_BLACK);
/* Perhaps we should start at 8, so0 that we only show 'active'
* keybindings?
*/
for (i=0; i<=MAX_KEYCODE; i++) {
for (key=keys[i]; key!=NULL; key =key->next) {
sprintf(buf,"%3d %s",count, get_key_info(key,i,0));
draw_info(buf,NDI_BLACK);
count++;
}
}
}
void bind_key(char *params)
{
char buf[MAX_BUF];
if (!params) {
draw_info("Usage: bind [-nfre] {<commandline>/commandkey/firekey{1/2}/runkey{1/2}}",NDI_BLACK);
return;
}
if (!strcmp(params, "commandkey")) {
bind_keycode = &commandkey;
bind_keysym = &commandkeysym;
draw_info("Push key to bind new commandkey.",NDI_BLACK);
cpl.input_state = Configure_Keys;
return;
}
if (!strcmp(params, "firekey1")) {
bind_keycode = &firekey[0];
bind_keysym = & firekeysym[0];
draw_info("Push key to bind new firekey 1.",NDI_BLACK);
cpl.input_state = Configure_Keys;
return;
}
if (!strcmp(params, "firekey2")) {
bind_keycode = &firekey[1];
bind_keysym = & firekeysym[1];
draw_info("Push key to bind new firekey 2.",NDI_BLACK);
cpl.input_state = Configure_Keys;
return;
}
if (!strcmp(params, "runkey1")) {
bind_keycode = &runkey[0];
bind_keysym = &runkeysym[0];
draw_info("Push key to bind new runkey 1.",NDI_BLACK);
cpl.input_state = Configure_Keys;
return;
}
if (!strcmp(params, "runkey2")) {
bind_keycode = &runkey[1];
bind_keysym = &runkeysym[1];
draw_info("Push key to bind new runkey 2.",NDI_BLACK);
cpl.input_state = Configure_Keys;
return;
}
if (params[0] != '-')
bind_flags =KEYF_MODIFIERS;
else {
bind_flags =0;
bind_keysym=NULL;
bind_keycode=NULL;
for (params++; *params != ' '; params++)
switch (*params) {
case 'n':
bind_flags |= KEYF_NORMAL;
break;
case 'f':
bind_flags |= KEYF_FIRE;
break;
case 'r':
bind_flags |= KEYF_RUN;
break;
case 'e':
bind_flags |= KEYF_EDIT;
break;
case '\0':
draw_info("Try unbind to remove bindings..",NDI_BLACK);
return;
default:
sprintf(buf, "Unknown flag to bind: '%c'", *params);
draw_info(buf,NDI_BLACK);
return;
}
params++;
}
if (!(bind_flags & KEYF_MODIFIERS))
bind_flags |= KEYF_MODIFIERS;
if (!params[0]) {
draw_info("Try unbind to remove bindings..",NDI_BLACK);
return;
}
sprintf(buf, "Push key to bind '%s'.", params);
draw_info(buf,NDI_BLACK);
strcpy(bind_buf, params);
bind_keycode=NULL;
cpl.input_state = Configure_Keys;
return;
}
/* This is a recursive function that saves all the entries for a particular
* entry. We save the first element first, and then go through
* and save the rest of the elements. In this way, the ordering of the key
* entries in the
* file remains the same.
*/
static void save_individual_key(FILE *fp, Key_Entry *key, KeyCode kc)
{
if (key==NULL) return;
fprintf(fp, "%s\n", get_key_info(key, kc, 1));
save_individual_key(fp, key->next, kc);
}
static void save_keys()
{
char buf[MAX_BUF], buf2[MAX_BUF];
int i;
FILE *fp;
sprintf(buf,"%s/.crossfire/keys", getenv("HOME"));
if ((fp=fopen(buf,"w"))==NULL) {
sprintf(buf2,"Could not open %s, key bindings not saved\n", buf);
draw_info(buf2,NDI_BLACK);
return;
}
for (i=0; i<=MAX_KEYCODE; i++) {
save_individual_key(fp, keys[i], i);
}
fclose(fp);
/* Should probably check return value on all writes to be sure, but... */
draw_info("key bindings successfully saved.",NDI_BLACK);
}
static void configure_keys(KeyCode k, KeySym keysym)
{
char buf[MAX_BUF];
if (bind_keycode==NULL) {
if(k == firekey[0] || k == firekey[1]) {
cpl.fire_on =1;
return;
}
if(k == runkey[0] || k == runkey[1]) {
cpl.run_on =1;
return;
}
}
cpl.input_state = Playing;
/* Try to be clever - take into account shift/control keys being
* held down when binding keys - in this way, player does not have to use
* -f and -r flags to bind for many simple binds.
*/
if ((cpl.fire_on || cpl.run_on) && (bind_flags & KEYF_MODIFIERS)==KEYF_MODIFIERS) {
bind_flags &= ~KEYF_MODIFIERS;
if (cpl.fire_on) bind_flags |= KEYF_FIRE;
if (cpl.run_on) bind_flags |= KEYF_RUN;
}
if (bind_keycode!=NULL) {
*bind_keycode = k;
*bind_keysym=keysym;
}
else {
insert_key(keysym, k, bind_flags, bind_buf);
}
sprintf(buf, "Binded to key '%s' (%i)", XKeysymToString(keysym), (int)k);
draw_info(buf,NDI_BLACK);
cpl.fire_on=0;
cpl.run_on=0;
/* Do this each time a new key is bound. This way, we are never actually
* storing any information that needs to be saved when the connection
* dies or the player quits.
*/
save_keys();
return;
}
void unbind_key(char *params)
{
int count=0, keyentry, onkey;
Key_Entry *key, *tmp;
char buf[MAX_BUF];
if (params==NULL || params[0]=='\0') {
show_keys();
return;
}
if ((keyentry=atoi(params))==0) {
draw_info("Usage: unbind <entry_number>",NDI_BLACK);
return;
}
for (onkey=0; onkey<=MAX_KEYCODE; onkey++) {
for (key=keys[onkey]; key; key =key->next) {
count++;
if (keyentry==count) {
if (key == keys[onkey]) {
keys[onkey] = key->next;
goto unbinded;
}
for (tmp=keys[onkey]; tmp->next!=NULL; tmp=tmp->next) {
if (tmp->next == key) {
tmp->next =key->next;
goto unbinded;
}
}
fprintf(stderr,"unbind_key - found number entry, but could not find actual key\n");
}
}
}
/* Makes things look better to draw the blank line */
draw_info("",NDI_BLACK);
draw_info("No such entry. Try 'unbind' with no options to find entry.",NDI_BLACK);
return;
/*
* Found. Now remove it.
*/
unbinded:
sprintf(buf,"Removed binding: %3d %s", count, get_key_info(key,onkey,0));
draw_info(buf,NDI_BLACK);
if (key->command) free(key->command);
free(key);
save_keys();
}